package org.firefligher.xscript;

import org.firefligher.xscript.exception.FunctionException;
import org.firefligher.xscript.exception.ParserException;

public class ScriptEngine {
	private VariableRegister varRegistry;
	private FunctionRegister funcRegistry;
	
	public ScriptEngine() {
		varRegistry = new VariableRegister();
		funcRegistry = new FunctionRegister();
	}
	
	public void parseCommand(String cmd) {
		if(cmd.contains("(") && cmd.contains(")") && cmd.contains(";")) {
			String func = cmd.split("\\(")[0];
			String[] pars = cmd.split("\\(")[1].replace(")", "").replace(";", "").split(",");
			String var = null;
			
			if(cmd.contains(") >")) {
				var = cmd.split("\\)")[1].replace(">", "").replace(";", "").replace(" ", "");
			}
			
			if(!(var == null)) {
				pars = cmd.replace(func, "").replace("(", "").split("\\)")[0].split(",");
			}
			
			FunctionReturn r = parseFunction(func, pars);
			if(var != null) {
				setVar(var, r);
			}
		} else {
			throw new ParserException("Command not found.");
		}
	}

	private void setVar(String var, FunctionReturn r) {
		varRegistry.addVariable(var, VariableContent.createFrom(r));
	}

	private FunctionReturn parseFunction(String name, String[] parameters) {
		FunctionParameter[] tmp = new FunctionParameter[parameters.length];
		
		for(int i = 0; i < parameters.length; i++) {
			tmp[i] = parseParameter(parameters[i]);
			
			if(tmp[i].getType().equals("other")) {
				tmp[i] = parseVarRegistry(tmp[i]);
			}
		}
		
		switch(name) {
		case "add":
			return new FunctionReturn("int", String.valueOf(Functions.add(tmp)));
		case "sub":
			return new FunctionReturn("int", String.valueOf(Functions.sub(tmp)));
		case "mul":
			return new FunctionReturn("int", String.valueOf(Functions.mul(tmp)));
		case "div":
			return new FunctionReturn("int", String.valueOf(Functions.div(tmp)));
		default:
			if(funcRegistry.contains(name))
				return funcRegistry.getFunction(name).execute(tmp);
			
			throw new FunctionException("Unknow function.");
		}
	}

	private FunctionParameter parseVarRegistry(FunctionParameter fp) {
		if(varRegistry.hasVariable(fp.getContent())) {
			return FunctionParameter.createFrom(varRegistry.getContent(fp.getContent()));
		}
		
		return fp;
	}

	private FunctionParameter parseParameter(String s) {
		FunctionParameter fp;
		
		try {
			fp = new FunctionParameter("int", String.valueOf(Integer.parseInt(s.replace(" ", ""))));
		} catch(Exception e) {
			fp = new FunctionParameter("other", s);
		}
		
		return fp;
	}

	public void addFunction(String name, Function f) {
		funcRegistry.addFunction(name, f);
	}
}
